// physical drive
package collector

import (
    "github.com/prometheus/client_golang/prometheus"
    "megacli_exporter/megacli"
)

type physicalDriveCollector struct {
    adapterNum            *prometheus.Desc
    slotNum               *prometheus.Desc
    mediaError            *prometheus.Desc
    otherError            *prometheus.Desc
    PredictiveFailure     *prometheus.Desc
    lastPredictiveFailure *prometheus.Desc
    driveTemperature      *prometheus.Desc
}

var subsystem = "physical_drive"
var namespace = "megacli"

func init() {
    prometheus.MustRegister(NewPhysicalDriveCollector())
}

func NewPhysicalDriveCollector() prometheus.Collector {

    return &physicalDriveCollector{
        adapterNum: prometheus.NewDesc(
            prometheus.BuildFQName(namespace, subsystem, "adapter_number"),
            "adapter number",
            []string{"slot"}, nil,
        ),
        slotNum: prometheus.NewDesc(
            prometheus.BuildFQName(namespace, subsystem, "slot_number"),
            "slot number",
            []string{"slot"}, nil,
        ),
        mediaError: prometheus.NewDesc(
            prometheus.BuildFQName(namespace, subsystem, "media_error"),
            "Media Error Count",
            []string{"slot"}, nil,
        ),
        otherError: prometheus.NewDesc(
            prometheus.BuildFQName(namespace, subsystem, "other_error"),
            "Other Error Count",
            []string{"slot"}, nil,
        ),
        PredictiveFailure: prometheus.NewDesc(
            prometheus.BuildFQName(namespace, subsystem, "predictive_failure"),
            "Predictive Failure Count.",
            []string{"slot"}, nil,
        ),
        lastPredictiveFailure: prometheus.NewDesc(
            prometheus.BuildFQName(namespace, subsystem, "last_predictive_failure"),
            "Last Predictive Failure Event Seq Number",
            []string{"slot"}, nil,
        ),
        driveTemperature: prometheus.NewDesc(
            prometheus.BuildFQName(namespace, subsystem, "temperature"),
            "Drive Temperature",
            []string{"slot"}, nil,
        ),
    }
}

func (c *physicalDriveCollector) Collect(ch chan<- prometheus.Metric) {

    cs, _ := megacli.GetControllers()

    for _, collector := range cs {
        _ = collector.Decode()
        for _, lg := range collector.LogDrives {
            for _, pd := range lg.PhyDrives {
                pdn := pd.SlotNumber
                ch <- prometheus.MustNewConstMetric(c.adapterNum, prometheus.GaugeValue, float64(collector.Number), pdn)
                ch <- prometheus.MustNewConstMetric(c.mediaError, prometheus.GaugeValue, float64(pd.MediaErrorCount), pdn)
                ch <- prometheus.MustNewConstMetric(c.otherError, prometheus.GaugeValue, float64(pd.OtherErrorCount), pdn)
                ch <- prometheus.MustNewConstMetric(c.PredictiveFailure, prometheus.GaugeValue, float64(pd.PredictiveFailureCount), pdn)
                ch <- prometheus.MustNewConstMetric(c.lastPredictiveFailure, prometheus.GaugeValue, float64(pd.LastPredictiveFailureCount), pdn)
                ch <- prometheus.MustNewConstMetric(c.driveTemperature, prometheus.GaugeValue, float64(pd.CurTemp), pdn)
            }
        }
    }

}

// Describe returns all descriptions of the collector.
func (c *physicalDriveCollector) Describe(ch chan<- *prometheus.Desc) {
    ch <- c.adapterNum
    ch <- c.slotNum
    ch <- c.mediaError
    ch <- c.otherError
    ch <- c.PredictiveFailure
    ch <- c.lastPredictiveFailure
    ch <- c.driveTemperature
}
